package com.sun.weight;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 非平滑加权轮询负载均衡算法实现
 * 这种算法按照权重比例分配请求，但分配不够平滑
 */
public class NonSmoothWeightedRoundRobin {

    // 服务器节点类
    public static class Server {
        private String name;
        private int weight;

        public Server(String name, int weight) {
            this.name = name;
            this.weight = weight;
        }

        public String getName() {
            return name;
        }

        public int getWeight() {
            return weight;
        }

        @Override
        public String toString() {
            return "Server{name='" + name + "', weight=" + weight + "}";
        }
    }

    private List<Server> servers; // 服务器列表
    private int totalWeight;      // 总权重
    private AtomicInteger currentIndex; // 当前索引

    public NonSmoothWeightedRoundRobin() {
        servers = new ArrayList<>();
        totalWeight = 0;
        currentIndex = new AtomicInteger(-1);
    }

    /**
     * 添加服务器
     * @param name 服务器名称
     * @param weight 服务器权重
     */
    public void addServer(String name, int weight) {
        if (weight <= 0) {
            throw new IllegalArgumentException("权重必须大于0");
        }
        servers.add(new Server(name, weight));
        totalWeight += weight;
    }

    /**
     * 获取下一台服务器 - 非平滑加权轮询算法
     * 算法原理：
     * 1. 计算所有服务器的总权重
     * 2. 使用一个递增的计数器，对总权重取模
     * 3. 遍历服务器列表，用余数依次减去每个服务器的权重
     * 4. 当余数小于某个服务器的权重时，选择该服务器
     * @return 被选中的服务器
     */
    public Server getNextServer() {
        if (servers.isEmpty()) {
            throw new IllegalStateException("没有可用的服务器");
        }
        // 使用原子递增确保线程安全
        int index = currentIndex.updateAndGet(i -> (i + 1) % totalWeight);
        // 遍历服务器列表，找到对应的服务器
        for (Server server : servers) {
            if (index < server.getWeight()) {
                return server;
            }
            index -= server.getWeight();
        }
        // 正常情况下不会执行到这里
        return servers.get(0);
    }

    /**
     * 打印服务器列表和权重信息
     */
    public void printServerInfo() {
        System.out.println("服务器列表:");
        for (Server server : servers) {
            System.out.println("  " + server.getName() + " - 权重: " + server.getWeight());
        }
        System.out.println("总权重: " + totalWeight);
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        // 创建负载均衡器
        NonSmoothWeightedRoundRobin lb = new NonSmoothWeightedRoundRobin();
        // 添加服务器及其权重
        lb.addServer("ServerA", 5); // 50%的请求
        lb.addServer("ServerB", 3); // 30%的请求
        lb.addServer("ServerC", 2); // 20%的请求
        // 打印服务器信息
        lb.printServerInfo();
        // 模拟20次请求分配
        System.out.println("\n请求分配情况:");
        for (int i = 0; i < 20; i++) {
            Server server = lb.getNextServer();
            System.out.println("请求 " + (i+1) + " 分配给: " + server.getName());
        }
        // 验证分配比例
        System.out.println("\n验证分配比例:");
        int[] count = new int[3]; // 统计每个服务器的请求次数
        for (int i = 0; i < 10000; i++) {
            Server server = lb.getNextServer();
            if ("ServerA".equals(server.getName())) {
                count[0]++;
            } else if ("ServerB".equals(server.getName())) {
                count[1]++;
            } else if ("ServerC".equals(server.getName())) {
                count[2]++;
            }
        }

        System.out.println("ServerA: " + count[0] + " 次 (" + (count[0]/100.0) + "%)");
        System.out.println("ServerB: " + count[1] + " 次 (" + (count[1]/100.0) + "%)");
        System.out.println("ServerC: " + count[2] + " 次 (" + (count[2]/100.0) + "%)");
    }
}